﻿using FluentParser.Expressions;
using FluentParser.Expressions.Rules.Composition;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Rules.Composition
{
    [TestClass]
    public class ChoiceSymbolRuleTests
    {
        [TestMethod]
        public void Parse_WhenLeftTokenMatch_ShouldReturnLeftTokenValue()
        {
            ChoiceSymbolRule choice = new ChoiceSymbolRule("LeftToken", "RightToken");
            ParsingResult<object> result = choice.Parse("LeftTokenAndSomethingElse");

            var expected = "LeftToken";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenRightTokenMatch_ShouldReturnRightTokenValue()
        {
            ChoiceSymbolRule choice = new ChoiceSymbolRule("LeftToken", "RightToken");
            ParsingResult<object> result = choice.Parse("RightTokenAndSomethingElse");

            var expected = "RightToken";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenNothingMatch_ShouldReturnNull()
        {
            ChoiceSymbolRule choice = new ChoiceSymbolRule("LeftToken", "RightToken");

            var expected = (ParsingResult<string>)null;
            var actual = choice.Parse("RightSomethingElse");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNode_WhenLeftTokenMatch_ShouldReturnLeftTokenValue()
        {
            ChoiceSymbolRule choice = new ChoiceSymbolRule("LeftToken", "RightToken");
            ParsingNodeResult node = choice.ParseNode("LeftTokenAndSomethingElse");

            string expected = "LeftToken";
            string actual = node.Value as string;

            Assert.IsTrue(node.IsSuccess);
            Assert.AreEqual(expected, actual);
            node.AssertLength(expected);
            node.AssertExploredLength(expected);

            node.AssertChildren(
                true); // LeftToken
        }

        [TestMethod]
        public void ParseNode_WhenRightTokenMatch_ShouldReturnRightTokenValue()
        {
            ChoiceSymbolRule choice = new ChoiceSymbolRule("LeftToken", "RightToken");
            ParsingNodeResult node = choice.ParseNode("RightTokenAndSomethingElse");

            string expected = "RightToken";
            string actual = node.Value as string;

            Assert.IsTrue(node.IsSuccess);
            Assert.AreEqual(expected, actual);
            node.AssertLength(expected);
            node.AssertExploredLength(expected);

            // Children check
            node.AssertChildren(
                false, // LeftToken
                true); // RightToken
        }

        [TestMethod]
        public void ParseNode_WhenNothingMatch_ShouldNotBeSuccessful()
        {
            ChoiceSymbolRule choice = new ChoiceSymbolRule("LeftToken", "RightToken");
            ParsingNodeResult node = choice.ParseNode("RightSomethingElse");

            string expected = null;
            string actual = node.Value as string;

            Assert.IsFalse(node.IsSuccess);
            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("Right?");

            // Children check
            node.AssertChildren(
                false, // LeftToken
                false); // RightToken
        }

    }
}